﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Threading;
using System.Drawing.Drawing2D;

namespace kiosk
{

    internal enum Fade
    {
        In,
        Out
    }
    public partial class Form1 : Form
    {
       public  DataBaseHandler dHandler;
       private List<string> msg;
       private static Mutex m_mutex = new Mutex();
       private static Mutex m_mutex2 = new Mutex();
       private Queue<String> messageQueue;
       TaskbarHide.FormState fm;
       
        #region forimageSideShow
        //
       
       
       private List<String> m_imagePathList;

       private const int PAUSE_TIME = 3 * 1000; 	//Time to display image
       private Image m_background;
       
       private MemoryStream m_ImageStream = null; 	//Current Loaded Image Stream
       private Image m_CurrentImage = null; 	//Current Loaded Image
       private int m_Alpha = 255; 			//Alpha level of the top layer of the image
       private Fade m_CurrentAction = Fade.In; 	//Current Action
       //Communicate between BackgroundWorker and Timer
       private AutoResetEvent m_FinishEvent = new AutoResetEvent(false);
      
       private AutoResetEvent m_reSizing = new AutoResetEvent(false);
      // private bool reSizeWorking = false;
       private Resample.ResamplingService reSizer = new Resample.ResamplingService();
       private AutoResetEvent m_msgEvent = new AutoResetEvent(false);
       private delegate void UpdateTimerEnableCallback(bool enabled);
       private delegate void UpdateMsg(String msg);
       //Define the display area, do not suggest calculate any formula in OnPaint 
       private bool m_stop = false;
       private bool m_imagestop = false;
       private Rectangle m_DisplayRectangle = new Rectangle();
      // private bool m_Cancel = false; 		//Flag to check Is the SlideShow cancelled
       private bool m_msgWork = false;
       private List<string> messages;
       private string m_nmsg;
       private delegate void UpdateImageListCallback(List<string> imagepaths);
       //
        #endregion

     
        public Form1()
        {
            InitializeComponent();
            //

            this.m_imagePathList = new List<string>();
            #region EventhAndlers
            this.englishBtn.Click += new EventHandler(englishBtn_Click);
            this.bengaliBtn.Click += new EventHandler(bengaliBtn_Click);
            this.nepaliBtn.Click +=new EventHandler(nepaliBtn_Click);
            this.ImgPictBox.Paint +=new PaintEventHandler(ImgPictBox_Paint);
           // this.timerfade.Tick +=new EventHandler(timerfade_Tick);
           // this.SSbackgroundWorker.DoWork +=new DoWorkEventHandler(SSbackgroundWorker_DoWork);
          
            this.label1.Click +=new EventHandler(label2_Click);
            #endregion

            #region folderSearch
            
            string[] path1 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.jpg");
            string[] path2 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.jpeg");
            string[] path3 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.bmp");

            foreach (string str in path1)
            {
                this.m_imagePathList.Add(str);
            
            }
            foreach (string str in path2)
            {
                this.m_imagePathList.Add(str);
            
            }
            foreach (string str in path3)
            {
                this.m_imagePathList.Add(str);
            
            }



            #endregion folderSearch
            
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

            // open the image file
            using (FileStream fs = File.Open(Application.StartupPath + @"\1.jpg", FileMode.Open))
            {




                byte[] ba = new byte[fs.Length];
                fs.Read(ba, 0, ba.Length);
                m_ImageStream = new MemoryStream(ba);
                //Clean up the current image
                if (m_background != null)
                {
                    m_background.Dispose();
                    m_background = null;
                }

                m_background = Image.FromStream(m_ImageStream);
            }

            // end of the background image
            //
            
             

        }

        

        private void Form1_Load(object sender, EventArgs e)
        
        {
            try
            {
                this.dHandler = new DataBaseHandler();
               
                dHandler.parpreConn();
                
                this.msg = this.dHandler.getGobalMassage();
                
                this.messageQueue = new Queue<string>();
                //hiding the taskbar
                fm= new TaskbarHide.FormState();
                fm.Maximize(this);
                //
                
                if (this.m_imagePathList.Count >= 1)
                {
                   // this.Start();
                
                }
                //
               

              //  this.imageWorkerStart();
                this.msgWorkerStart();

            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                this.Close();

            }

            
            // open the image file

          


       
      }

        
        


       

        private void englishBtn_Click(object sender, EventArgs e)
        {

            // create a new Bengali form and show it to the user

            // check to see if any data present in the database to display it
            try
            {
                this.TopMost = false;
                Int32 lanid = dHandler.getLanIDOnLanName("English");
                
                Int32 gid = dHandler.getFirstLanGroupID(lanid);
                DataTable items = this.dHandler.getAllGroupItems(gid);
                if (gid == -1 || (items.Rows.Count < 1))
                { 
                   // no data present in the database
                    GBTextInput gbtext = new GBTextInput();
                    gbtext.ShowDialog();
                    return;
                
                }

                DisplayButtons butt = new DisplayButtons(gid, dHandler);
               
                butt.ShowDialog();
                this.TopMost = true;
               
              
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + " Critical error please contract admin");

            }


           

        }

        private void bengaliBtn_Click(object sender, EventArgs e)
        {

            // the Bengali button in the system

            try {
                this.TopMost = false;
                Int32 lanid = dHandler.getLanIDOnLanName("Bengali");
                Int32 gid = dHandler.getFirstLanGroupID(lanid);
                DataTable items = this.dHandler.getAllGroupItems(gid);
                if (gid == -1 || (items.Rows.Count <1 ))
                {
                    // no data present in the database
                    GBTextInput gbtext = new GBTextInput();
                    gbtext.ShowDialog();
                    return;

                }
                DisplayButtons butt = new DisplayButtons(gid, dHandler);
                butt.ShowDialog();
                this.TopMost = true;
            
            }
            catch(Exception ex)
            {

                MessageBox.Show(ex.Message + "   ----- error please contract admin");
                return;
            }



        }


        private void nepaliBtn_Click(object sender, EventArgs e)
        {


            try
            {
                this.TopMost = false;
                Int32 lanid = dHandler.getLanIDOnLanName("Nepali");
                Int32 gid = dHandler.getFirstLanGroupID(lanid);
                DataTable items = this.dHandler.getAllGroupItems(gid);
                if (gid == -1 || (items.Rows.Count < 1))
                {
                    // no data present in the database
                    GBTextInput gbtext = new GBTextInput();
                    gbtext.ShowDialog();
                    return;

                }
                DisplayButtons butt = new DisplayButtons(gid, dHandler);
                butt.ShowDialog();
                this.TopMost = true;

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message + "   ----- error please contract admin");
                return;
            }



        }


        protected override void OnClosed(EventArgs e)
        {
            
            base.OnClosed(e);
           
           
        }



        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys.Control | Keys.G))
            {
                this.TopMost = false;
                GBTextInput gbtext = new GBTextInput();
                gbtext.ShowDialog();
                this.TopMost = true;

           }

            if (keyData == Keys.F1)
            {
                this.TopMost = false;
                AboutBox1 ab = new AboutBox1();
                ab.ShowDialog();
                this.TopMost = true;
              
            
            }
            if (keyData == (Keys.Control | Keys.M))
            {
                this.TopMost = false;
                GobalMessages message = new GobalMessages();
                message.ShowDialog();
                this.TopMost = true;
            
            
            }
            if (keyData == (Keys.Control | Keys.H))
            {
                this.fm.Restore(this);
            
            }

           return base.ProcessCmdKey(ref msg, keyData);
       }

       
      
       

       

        private void label2_Click(object sender, EventArgs e)
        {
            this.TopMost = false;
            // Open the webpage window
            webPage wb = new webPage();
            wb.ShowDialog();
            this.TopMost = true;

        }

      
        private void timerfade_Tick(object sender, EventArgs e)
        {

            if ((m_CurrentAction == Fade.In) && (m_Alpha > 0))
            {
                if(this.TopMost)
                m_Alpha -= 5;
            }
            else if ((m_CurrentAction == Fade.Out) && (m_Alpha < 255))
            {
                if(this.TopMost)
                m_Alpha += 5;
            }
            if ((m_Alpha <= 0) || (m_Alpha >= 255))
            {
                //Fire the event to BackgroundWorker to change the image
                if (this.TopMost)
                {
                    m_FinishEvent.Set();
                    this.timerfade.Enabled = false;
                }  
            
            }
            
            
            this.ImgPictBox.Invalidate();
            
        }


        private void SSbackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // main worker thread
            List<String> imagepath = (List<string>)e.Argument;

            int i = 0;

            while (true)
            {
                

                if (m_stop)
                {
                    break;

                }
                if (this.SSbackgroundWorker.CancellationPending)
                {
                   
                    break;
                
                }


                m_CurrentAction = Fade.Out;
                this.UpdateTimerEnable(true);
                //Wait for Timer to finish fade out effect
                

                if (m_stop)
                {
                    break;

                }
                if (this.SSbackgroundWorker.CancellationPending)
                {
                    break;

                }


                //Clean up the image stream
                if (m_ImageStream != null)
                {
                    m_ImageStream.Dispose();
                    m_ImageStream = null;
                }

                // MUtex code
                Form1.m_mutex.WaitOne();
                
                using (FileStream fs = File.Open(imagepath[i], FileMode.Open))
                {
                    i = i + 1;
                    
                    if (i == imagepath.Count)
                    {
                        i = 0;
                    }

                   

                    byte[] ba = new byte[fs.Length];
                    fs.Read(ba, 0, ba.Length);
                    m_ImageStream = new MemoryStream(ba);
                    //Clean up the current image
                    
                    Form1.m_mutex2.WaitOne();
                    
                    if (m_CurrentImage != null)
                    {
                        m_CurrentImage.Dispose();
                        m_CurrentImage = null;
                    }

                    m_CurrentImage = Image.FromStream(m_ImageStream);
                    // check if image size is larger then the client size
                     //Testing Code
                    Form1.m_mutex2.ReleaseMutex();
                    Form1.m_mutex.ReleaseMutex();

                    this.PictResize(this.ImgPictBox.ClientSize.Width,this.ImgPictBox.ClientSize.Height);

                   //
                    int x = (this.ImgPictBox.ClientSize.Width - m_CurrentImage.Width) / 2;
                    int y = (this.ImgPictBox.ClientSize.Height - m_CurrentImage.Height) / 2;
                    m_DisplayRectangle = new Rectangle(x, y, m_CurrentImage.Width, m_CurrentImage.Height);

                }
                                            
                m_CurrentAction = Fade.In;
                UpdateTimerEnable(true);
                //Wait for Timer to finish fade in effect
               
                //Sleep for display the image
                Thread.Sleep(PAUSE_TIME);

            }
            
          


        }


        private void UpdateTimerEnable(bool enabled)
        {
            if (this.InvokeRequired)
            {
                UpdateTimerEnableCallback d = new UpdateTimerEnableCallback(UpdateTimerEnable);
                try
                {
                    this.BeginInvoke(d, new object[] { enabled });
                   
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                
              }
            else
            {
                timerfade.Enabled = enabled;
            }
        }

        private void upMsgText(String msg)
        {
            if (this.InvokeRequired)
            {
                UpdateMsg d = new UpdateMsg(this.upMsgText);
                this.Invoke(d, new Object[] { msg });


            }
            else
            {

                this.m_nmsg = msg;
                this.tickerImg.Invalidate();
               
                this.m_msgEvent.Set(); 
            
            }

        
        
        }




        private void ImgPictBox_Paint(object sender, PaintEventArgs e)
        {

            Form1.m_mutex2.WaitOne();
            if (m_CurrentImage != null && this.TopMost)
            {
                Graphics g = e.Graphics; //Graphics.FromImage(m_CurrentImage);
                //this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
                //this.pictureBox1.Location = new System.Drawing.Point(162, 3);
                g.DrawImage(m_CurrentImage, m_DisplayRectangle,
                  0, 0, m_CurrentImage.Width, m_CurrentImage.Height, GraphicsUnit.Pixel);
                //Draw the layer to effect fade in and out, 
                //the layer is same as window background color
                
                g.FillRectangle(new SolidBrush(Color.FromArgb(m_Alpha, Color.White)), this.ImgPictBox.ClientRectangle);
                
            }
            Form1.m_mutex2.ReleaseMutex();



        }


        private void Start()
        {
            if (SSbackgroundWorker.IsBusy)
            {
                
                Stop();
            
            }
            
            SSbackgroundWorker.RunWorkerAsync(this.m_imagePathList);
            m_stop = false;
            
           
        }

        private void Stop()
        {
            if (SSbackgroundWorker.IsBusy)
            {
               
                SSbackgroundWorker.CancelAsync();
                m_stop = true;
               
            }
        }

       




       


        private void imageWorkerStart()
        {
            if (imgFolderCheckWorker.IsBusy)
            {
                Stop();
            }
            imgFolderCheckWorker.RunWorkerAsync(this.m_imagePathList);


            m_imagestop = false;
        }

        private void imageWorkerStop()
        {
            if (imgFolderCheckWorker.IsBusy)
            {
                imgFolderCheckWorker.CancelAsync();

                m_imagestop = true;
            }
        }

      
        private void imgFolderCheckWorker_DoWork(object sender, DoWorkEventArgs e)
        {



            List<string> dupImagePath = (List<string>)e.Argument;
            List<String> imagePath = new List<string>();
             
            while (true)
            {
                
                
                if(this.m_imagestop)
                {
                    break;
                }
                
                #region folderSearch
                
                

                string[] path1 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.jpg");
                string[] path2 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.jpeg");
                string[] path3 = Directory.GetFiles(Application.StartupPath + @"\picture\", "*.bmp");
               

               

                imagePath.Clear();

                foreach (string str in path1)
                {
                    imagePath.Add(str);

                }
                foreach (string str in path2)
                {
                    imagePath.Add(str);

                }
                foreach (string str in path3)
                {
                    imagePath.Add(str);

                }



                #endregion folderSearch

                if (imagePath.Count != dupImagePath.Count)
                {
                    // set the Event
                    Form1.m_mutex.WaitOne();

                    if (dupImagePath != null)
                    {

                        dupImagePath.Clear();
                        foreach (string str in imagePath)
                        {
                            dupImagePath.Add(str);

                        }


                    }
                    else
                    {
                        dupImagePath = imagePath;

                    }
                    if(!this.SSbackgroundWorker.IsBusy)
                    {

                        this.Start();
                    
                    }

                    Form1.m_mutex.ReleaseMutex();

                }
                 

            }

        }

        private void SSbackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            Console.WriteLine("Work completed for the last");

        }

        
        // Worker that gets all the messages from the database and displays to the user
        
        private void msgWorker_DoWork(object sender, DoWorkEventArgs e)
        {

            bool fetchData = true;
            DataBaseHandler handler = new DataBaseHandler();
            handler.parpreConn();

            while(true)
            {
                if (this.m_msgWork)
                {
                    break;
                }
                if (this.msgWorker.CancellationPending)
                {
                    break;

                }


                // get the all the messages from the dataBase
               
                if(fetchData)
                {

                    if (this.messages != null)
                    {
                        this.messages.Clear();
                        this.messages = null;
                    }

               
                messages = handler.getGobalMassage();
                fetchData = false;
                }

                // upDate the label of the main window

                foreach (string str in messages)
                {

                    this.upMsgText(str);
                    this.m_msgEvent.WaitOne();
                    Thread.Sleep(PAUSE_TIME);
                
                
                }
                fetchData = true;
                
            }
        
        }



        private void msgWorkerStart()
        {
            if (msgWorker.IsBusy)
            {
                Stop();
            }
            msgWorker.RunWorkerAsync(null);


            m_msgWork = false;
        }

        private void msgWorkerStop()
        {
            if (msgWorker.IsBusy)
            {
                msgWorker.CancelAsync();

                m_msgWork = true;
            }
        }


        #region imageResize
        public void PictResize(int newWidth, int newHeight)
        {
            if (newWidth != 0 && newHeight != 0)
            {
                Form1.m_mutex2.WaitOne();
                Bitmap temp = (Bitmap)this.m_CurrentImage.Clone();
                Form1.m_mutex2.ReleaseMutex();
                
                Bitmap bmap = new Bitmap(newWidth, newHeight, temp.PixelFormat);

                double nWidthFactor = (double)temp.Width / (double)newWidth;
                double nHeightFactor = (double)temp.Height / (double)newHeight;

                double fx, fy, nx, ny;
                int cx, cy, fr_x, fr_y;
                Color color1 = new Color();
                Color color2 = new Color();
                Color color3 = new Color();
                Color color4 = new Color();
                byte nRed, nGreen, nBlue;

                byte bp1, bp2;

                for (int x = 0; x < bmap.Width; ++x)
                {
                    for (int y = 0; y < bmap.Height; ++y)
                    {

                        fr_x = (int)Math.Floor(x * nWidthFactor);
                        fr_y = (int)Math.Floor(y * nHeightFactor);
                        cx = fr_x + 1;
                        if (cx >= temp.Width) cx = fr_x;
                        cy = fr_y + 1;
                        if (cy >= temp.Height) cy = fr_y;
                        fx = x * nWidthFactor - fr_x;
                        fy = y * nHeightFactor - fr_y;
                        nx = 1.0 - fx;
                        ny = 1.0 - fy;

                        color1 = temp.GetPixel(fr_x, fr_y);
                        color2 = temp.GetPixel(cx, fr_y);
                        color3 = temp.GetPixel(fr_x, cy);
                        color4 = temp.GetPixel(cx, cy);

                        // Blue
                        bp1 = (byte)(nx * color1.B + fx * color2.B);

                        bp2 = (byte)(nx * color3.B + fx * color4.B);

                        nBlue = (byte)(ny * (double)(bp1) + fy * (double)(bp2));

                        // Green
                        bp1 = (byte)(nx * color1.G + fx * color2.G);

                        bp2 = (byte)(nx * color3.G + fx * color4.G);

                        nGreen = (byte)(ny * (double)(bp1) + fy * (double)(bp2));

                        // Red
                        bp1 = (byte)(nx * color1.R + fx * color2.R);

                        bp2 = (byte)(nx * color3.R + fx * color4.R);

                        nRed = (byte)(ny * (double)(bp1) + fy * (double)(bp2));

                        bmap.SetPixel(x, y, System.Drawing.Color.FromArgb
                (255, nRed, nGreen, nBlue));
                    }
                }
                this.m_CurrentImage = (Bitmap)bmap.Clone();
            }
        }

        public Image ScalImage(Image imgToResize, Size size)
        {

            int sourceWidth = imgToResize.Width;
            int sourceHeight = imgToResize.Height;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)size.Width / (float)sourceWidth);
            nPercentH = ((float)size.Height / (float)sourceHeight);

            if (nPercentH < nPercentW)
                nPercent = nPercentH;
            else
                nPercent = nPercentW;

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap b = new Bitmap(destWidth, destHeight);

            using (Graphics g = Graphics.FromImage((Image)b))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
            }


            return (Image)b;
        }



        #endregion

        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {
            

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
           // draw the picture

            Graphics g = e.Graphics;
            if (m_background != null)
            {
                g.DrawImage(m_background, new Rectangle(0,0,this.Width,this.Height),
                     0, 0, m_background.Width, m_background.Height, GraphicsUnit.Pixel);
            
            }


        }

        private void tableLayoutPanel1_Resize(object sender, EventArgs e)
        {
            
            
        }

       

        
        private void tickerImg_Paint(object sender, PaintEventArgs e)
        {
            Console.WriteLine("Image Ticker");
            System.Drawing.Font f = new Font("Arial", 12, FontStyle.Italic);

            if (this.m_nmsg != null)
            {
                Graphics g = e.Graphics;
                g.DrawString(this.m_nmsg, f, new SolidBrush(Color.FromArgb(255, Color.Black)), 0, 0);

            }


        }

        private void glassButton1_Click(object sender, EventArgs e)
        {
            this.TopMost = false;
            MainForm m = new MainForm();
            m.ShowDialog();
            this.TopMost = true;


        }


    }

}
